home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!gatech!ukma!cwjcc!hal!ncoast!allbery
- From: joe@dayton.DHDSC.MN.ORG (Joseph P. Larson)
- Newsgroups: comp.sources.misc
- Subject: v04i118: fcpio - a fast cpio partial replacement
- Message-ID: <8810050954.AA27269@dayton.DHDSC.MN.ORG>
- Date: 7 Oct 88 00:16:54 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: joe@dayton.DHDSC.MN.ORG (Joseph P. Larson)
- Lines: 379
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 118
- Submitted-by: "Joseph P. Larson" <joe@dayton.DHDSC.MN.ORG>
- Archive-name: fcpio
-
- In any case, I wrote up the enclosed program one day when I got a little
- too annoyed with cpio while dealing with some rather large cpio archives.
- It doesn't need a makefile (I just say make fcpio). The two include files
- are from our <dayton/> directory, so people will need to patch the .c a
- little to specify where these came from. (They AREN'T replacements for
- the regular includes of the same name!)
-
- Hope someone finds this useful. -Joe
-
-
- ----Cut Here----
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # fcpio.doc
- # fcpio.c
- # math.h
- # stdtyp.h
- # This archive created: Wed Oct 5 09:54:01 1988
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'fcpio.doc'
- then
- echo shar: "will not over-write existing file 'fcpio.doc'"
- else
- cat << \SHAR_EOF > 'fcpio.doc'
- PROGRAM:
-
- fcpio -- a fast cpio for seekable devices
-
-
- SYNOPSIS:
-
- fcpio [-options] archive-name [extract-pattern1 [ ... extract-patternn]]
-
- Options implemented to date:
-
- x - extract files
- t - table of contents
-
-
- DESCRIPTION:
-
- fcpio is a partial cpio (tm Ma Bell) replacement. It is very useful
- when performing extracts or retrieving a table of contents from a
- disk-resident cpio archive. This is due to use of seeks to skip over
- unwanted data. (Our copy of cpio reads through everything as it must
- assume it can't seek.) Thus, a -t on a 3.3 Meg file runs at output
- (9600 baud) speeds with fcpio but has long pauses with cpio at all the
- long (> 20K) files within the archive. An extract of a few items is
- also very fast.
-
- The extract patterns do not support wild carding or anything fancy --
- fcpio will extract any files that begin with one of the extract patterns
- (or all files if no extract pattern is specified).
-
-
- AUTHOR:
-
- Joe Larson
- Dayton-Hudson Department Store Company
- 700 On the Mall
- Minneapolis, Minnesota 55402
-
- 612-375-3537
-
-
- BUGS:
-
- 1. Does not support non-seekable devices (like pipes?)
- 2. Does not maintain the files original magic number, UID or GID.
- 3. May not handle garbage at the end of the archive terribly well.
- (Our cpio puts an item called "TRAILER!!!" at the end, so fcpio
- equates that with EOF as well as ending on EOF. Other cpios
- may behave differently....)
- SHAR_EOF
- fi
- if test -f 'fcpio.c'
- then
- echo shar: "will not over-write existing file 'fcpio.c'"
- else
- cat << \SHAR_EOF > 'fcpio.c'
- #include <stdio.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <dayton/math.h>
- #include <dayton/stdtyp.h>
-
- /*
- * fcpio - fast cpio for seek-able devices.
- *
- * Usage:
- *
- * fcpio [-options] cpio-archive [extract-pattern-list]
- *
- * Implemented options are:
- *
- * x - extract the named extract-pattern files.
- * t - print a table of contents.
- *
- * In extract mode, the extracted files are the ones whose names begin
- * with anything in the named list. Skipped items are displayed
- * by a "." to indicate progress being made.
- *
- * Author:
- *
- * Joe Larson
- * Dayton-Hudson Dept. Store Co.
- * 700 On The Mall
- * Minneapolis, Minnesota 55402
- *
- * UUCP:joe@dayton
- */
-
- struct Hdr
- {
- short h_magic,
- h_dev;
- ushort h_ino,
- h_mode,
- h_uid,
- h_gid,
- h_nlink,
- h_rdev,
- h_mtime[2],
- h_namesize,
- h_filesize[2];
- char h_name[80];
- };
-
- #define READBUFSIZE 100000
- char readbuf[READBUFSIZE];
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- struct Hdr hstruct; /* Indiv. file header in ifile. */
- int ifile, /* Archive file */
- cur_pos, /* Position in ifile */
- fpos, /* Another position in ifile */
- dummy, /* Holds length of current file in ifile */
- i, /* Counter for lots of things */
- ilens[20], /* Lengths of x_names[]. */
- count, /* # of files we've skipped. */
- x_count, /* Number of x_names[]. */
- isize; /* Used in seeking... */
- char *a_name, /* Name of archive file */
- *options, /* Option string from cmnd line. */
- *x_names[20]; /* Name of extract file beginnings. */
- bool do_extract, /* Extract files? */
- do_table, /* Do a table of contents? */
- x_here; /* Extract this file? */
-
- a_name = NULL;
- options = "x";
- x_count = 0;
- do_extract = 0;
- do_table = 0;
- for (i = 1; i < argc; i++)
- {
- if (*argv[i] == '-')
- options = argv[i]+1;
- else if (a_name == NULL)
- a_name = argv[i];
- else
- x_names[x_count++] = argv[i];
- }
- if (a_name == NULL)
- {
- usage(argv[0]);
- exit(0);
- }
- do_extract = (strchr(options, 'x') != NULL);
- do_table = (strchr(options, 't') != NULL);
- ifile = open(a_name, O_RDONLY);
- if (ifile == -1)
- {
- perror(a_name);
- exit(errno);
- }
- for (i = 0; i < x_count; i++)
- ilens[i] = strlen(x_names[i]);
- cur_pos = 0;
- count = 0;
- while(1)
- {
- if (read(ifile, &hstruct, sizeof(struct Hdr)) < sizeof(struct Hdr))
- break;
- if (!strcmp(hstruct.h_name, "TRAILER!!!"))
- break;
- dummy = (hstruct.h_filesize[0] << 16) + hstruct.h_filesize[1];
- if (do_table)
- {
- fprintf(stderr, "%6ld %s\n", dummy, hstruct.h_name);
- fflush(stderr);
- }
- isize = (hstruct.h_namesize + 1) & ~(1L);
- if (do_extract)
- {
- x_here = !(x_count); /* If no x_names, extract all */
- for (i = 0; i < x_count; i++)
- if (!strncmp(x_names[i], hstruct.h_name, ilens[i]))
- {
- x_here = 1;
- break;
- }
- if (x_here)
- {
- if (count)
- fprintf(stderr, "\n");
- count = 0;
- fpos = cur_pos + sizeof(struct Hdr) - 80 + isize;
- fprintf(stderr, "X: %s", hstruct.h_name);
- fflush(stderr);
- copy_file(ifile, fpos, &hstruct, dummy);
- fprintf(stderr, ".\n");
- }
- else
- {
- fprintf(stderr, ".");
- if (++count == 60)
- {
- fprintf(stderr, "\n");
- count = 0;
- }
- else
- fflush(stderr);
- }
- }
- cur_pos += (dummy + sizeof(struct Hdr) - 80 + isize + 1) & ~(1L);
- lseek(ifile, cur_pos, 0);
- }
- close(ifile);
- }
-
-
- copy_file(ifile, fpos, hstruct, ilen)
- int ifile, fpos, ilen;
- struct Hdr *hstruct;
- /*
- * Copy out this file. This routine still needs to do some things.
- *
- * For instance, no attempt is made to preserve the original files
- * magic number, c/m/a times, owner or group.
- */
- {
- int ofile, rlen, nlen;
- char name[132], *c1, *c2;
-
- if (hstruct->h_mode & 0040000L)
- {
- make_path(hstruct->h_name, 1);
- return;
- }
- for (c1 = NULL, c2=hstruct->h_name; *c2; c2++)
- if (*c2 == '/')
- c1 = c2;
- if (c1 != NULL)
- {
- nlen = c1 - hstruct->h_name;
- strncpy(name, hstruct->h_name, nlen);
- name[nlen] = 0;
- make_path(name, 1);
- }
- ofile = open(hstruct->h_name, O_WRONLY | O_CREAT, hstruct->h_mode&07777L);
- if (ofile == -1)
- {
- perror(hstruct->h_name);
- return;
- }
- lseek(ifile, fpos, 0L);
- while (ilen > 0)
- {
- rlen = MIN(READBUFSIZE, ilen);
- rlen = read(ifile, readbuf, rlen);
- if (rlen > 0)
- write(ofile, readbuf, rlen);
- else
- break;
- ilen -= rlen;
- }
- close(ofile);
- }
-
-
-
- usage(arg)
- char *arg;
- {
- fprintf(stderr, "Usage: %s infilename\n", arg);
- }
-
- make_path(p, flag)
- char *p, flag;
- /*
- * Make sure this entire pathname exists.
- */
- {
- short ilen;
- char name[132], *c1, *c2;
-
- if (access(p, 00))
- {
- if (flag)
- {
- for (c1 = NULL, c2 = p; *c2; c2++)
- {
- if (*c2 == '/')
- {
- if (c1 != NULL)
- {
- ilen = c2 - p;
- strncpy(name, p, ilen);
- name[ilen] = 0;
- if (access(name, 00))
- make_path(p, 0);
- }
- c1 = c2;
- }
- }
- }
- if (!fork())
- {
- execlp("mkdir", "mkdir", p, 0);
- exit(errno);
- }
- else
- wait(0);
- }
- }
- SHAR_EOF
- fi
- if test -f 'math.h'
- then
- echo shar: "will not over-write existing file 'math.h'"
- else
- cat << \SHAR_EOF > 'math.h'
- /*
- * Dayton's math library definitions.
- */
-
- #define MIN(x,y) ((x < y) ? x : y)
- #define MAX(x,y) ((x > y) ? x : y)
- #define ABS(x) ((x < 0) ? -x : x)
- SHAR_EOF
- fi
- if test -f 'stdtyp.h'
- then
- echo shar: "will not over-write existing file 'stdtyp.h'"
- else
- cat << \SHAR_EOF > 'stdtyp.h'
- /*
- * Standard types and defines for Dayton-Hudson.
- *
- */
-
- #include <stdtyp.h>
-
- #ifndef TRUE
- #define TRUE (1)
- #endif
-
- #ifndef FALSE
- #define FALSE (0)
- #endif
-
- #define ULONG unsigned long
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-